FUNCTION MODULE ZSTB_RFC_SQL_SELECT
FUNCTION GROUP  ZSTB_FUNCTION_GROUP
DESCRIPTION     select data from table
PROCESSING TYPE : remote-enable module

IMPORT
PARAMETER       |TYPE_SPEC|ASSOCIATED_TYPE        |DEFAULT|OPTIONAL|PASS_VALUE|DESCRIPTION         
----------------|---------|-----------------------|-------|--------|----------|--------------------
FIELD_SEPARATOR |TYPE     |ZSTB_FIELD_SEP_TYPE    |','    |YES     |YES       |CSV field separator 
STRING_DELIMITER|TYPE     |ZSTB_STRING_DELIM_TYPE |'"'    |YES     |YES       |CSV string delimiter
FETCH_SIZE      |TYPE     |ZSTB_FETCH_SIZE_TYPE   |1024   |YES     |YES       |fetch size          
MAX_LINE_NUMBER |TYPE     |ZSTB_LINE_NUMBER_TYPE  |0      |YES     |YES       |maximum line number 
SESSION_ID      |TYPE     |ZSTB_SESSION_ID_TYPE   |       |NO      |YES       |session ID          
REQUEST_UUID    |TYPE     |ZSTB_REQUEST_UUID_TYPE |       |NO      |YES       |request UUID        
ROW_SEPARATOR   |TYPE     |ZSTB_ROW_SEPARATOR_TYPE|'\r\n' |YES     |YES       |row separator       

EXPORT
PARAMETER       |TYPE_SPEC|ASSOCIATED_TYPE       |PASS_VALUE|DESCRIPTION         
----------------|---------|----------------------|----------|--------------------
MAX_FETCH_NUMBER|TYPE     |ZSTB_FETCH_NUMBER_TYPE|YES       |maximum fetch number

TABLES
PARAMETER  |TYPE_SPEC|ASSOCIATED_TYPE         |OPTIONAL|DESCRIPTION            
-----------|---------|------------------------|--------|-----------------------
FIELDS     |LIKE     |ZSTB_SQL_CLAUSE_ELEMENTS|NO      |fields to select       
FROMCLAUSE |LIKE     |ZSTB_SQL_CLAUSE_ELEMENTS|NO      |tables to select (from)
WHERECLAUSE|LIKE     |ZSTB_SQL_CLAUSE_ELEMENTS|NO      |filters (where)        

SOURCE CODE
...........
function zstb_rfc_sql_select .
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(FIELD_SEPARATOR) TYPE  ZSTB_FIELD_SEP_TYPE DEFAULT ','
*"     VALUE(STRING_DELIMITER) TYPE  ZSTB_STRING_DELIM_TYPE DEFAULT '"'
*"     VALUE(FETCH_SIZE) TYPE  ZSTB_FETCH_SIZE_TYPE DEFAULT 1024
*"     VALUE(MAX_LINE_NUMBER) TYPE  ZSTB_LINE_NUMBER_TYPE DEFAULT 0
*"     VALUE(SESSION_ID) TYPE  ZSTB_SESSION_ID_TYPE
*"     VALUE(REQUEST_UUID) TYPE  ZSTB_REQUEST_UUID_TYPE
*"     VALUE(ROW_SEPARATOR) TYPE  ZSTB_ROW_SEPARATOR_TYPE DEFAULT
*"       '\r\n'
*"  EXPORTING
*"     VALUE(MAX_FETCH_NUMBER) TYPE  ZSTB_FETCH_NUMBER_TYPE
*"  TABLES
*"      FIELDS STRUCTURE  ZSTB_SQL_CLAUSE_ELEMENTS
*"      FROMCLAUSE STRUCTURE  ZSTB_SQL_CLAUSE_ELEMENTS
*"      WHERECLAUSE STRUCTURE  ZSTB_SQL_CLAUSE_ELEMENTS
*"----------------------------------------------------------------------

type-pools: abap.
data:
  columnname type so_text,
  numberfields type i,
  fielddescr type abap_componentdescr,
  fieldname type string,
  fielddescrtab type abap_component_tab,
  rowstructdescr type ref to cl_abap_structdescr,
  rowreference type ref to data,
  fromclauserow type zstb_sql_clause_elements,
  fromclausestring type string,
  whereclauserow type zstb_sql_clause_elements,
  whereclausestring type string,
  fieldsrow type zstb_sql_clause_elements,
  max_line_count type i,
  line_numbers_to_process type i,
  table_cursor type cursor,
  fetch_number type i,
  line_number type i.
field-symbols: <datarow> type any.

* create datastructure with field names
* datatypes are read from fieldnames of fields input table
describe table fields lines numberfields.
loop at fields into fieldsrow.
  fieldname = sy-tabix.
* names need to be unique and must start with a char
  concatenate 'string' fieldname into fieldname.
  condense fieldname.
  fielddescr-name = fieldname.
* for dictionary lookup we need to change columnnames from open sql to dictionary notation
  columnname = fieldsrow-text.
  replace first occurrence of substring '~' in columnname with '-' respecting case.
  fielddescr-type ?= cl_abap_typedescr=>describe_by_name( columnname ).
  append fielddescr to fielddescrtab.
endloop.

* now we create the actual data structure in memory
rowstructdescr = cl_abap_structdescr=>create( fielddescrtab ).
create data rowreference type handle rowstructdescr.
* finally we assign it to the field-symbol used by the select statement
assign rowreference->* to <datarow>.

* to simplify calls we concatenate from and whereclause into strings
* this way caller doesn't need to check word wrappings
fromclausestring = ''.
loop at fromclause into fromclauserow.
  concatenate fromclausestring fromclauserow-text
  into fromclausestring separated by space.
endloop.

whereclausestring = ''.
loop at whereclause into whereclauserow.
  concatenate whereclausestring whereclauserow-text
  into whereclausestring separated by space.
endloop.

* set number of line to process
select count(*) from (fromclausestring) into max_line_count where (whereclausestring).
line_numbers_to_process = max_line_number.
if line_numbers_to_process <= 0 or line_numbers_to_process > max_line_count.
  line_numbers_to_process = max_line_count.
endif.

* now start actual select operation
fetch_number = 0.
line_number = 0.
* INFO : regarding some sap forums, an offset parameter should exist to manage stating line
*        however, i did not succed to use it in this context
*        see : https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abapselect_up_to_offset.htm#!abap_addition_2@2@
open cursor table_cursor for
select (fields) from (fromclausestring) up to line_numbers_to_process rows where (whereclausestring).
* we read all fields of the current row, cast it to string and
* concatenate it into a dataline with division chars.
do line_numbers_to_process times.
* insert into transfert table
  fetch next cursor table_cursor into <datarow>.
  call function 'ZSTB_INSERT_TRANSF_TBL'
    exporting
      numberfields = numberfields
      datarow = <datarow>
      string_delimiter = string_delimiter
      field_separator = field_separator
      row_separator = row_separator
      session_id = session_id
      request_uuid = request_uuid
      fetch_number = fetch_number
      line_number = line_number.
* next line
  line_number = line_number + 1.
  if line_number = fetch_size.
    fetch_number = fetch_number + 1.
    line_number = 0.
  endif.
enddo.
close cursor table_cursor.

* return maximum fetch number
max_fetch_number = fetch_number.

endfunction.